package com.jie.eclipse.pan.xml;

import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;

import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

import com.jie.eclipse.pan.data.BaseDataEntities;
import com.jie.eclipse.pan.data.BaseDataEntity;
import com.jie.eclipse.pan.utils.StringHelper;
import com.jie.eclipse.pan.utils.Utils;


/**
 * XML 节点
 * 
 * @author yanjie
 * 
 */
public class XMLNode extends XMLConfig
{
	protected ArrayList<XMLNode> childNodes = null;

	protected XMLNode parentNode = null;

	protected String strXMLNodeId = "";

	protected String strPXMLNodeId = null;

	protected int nOrderFlag = 1000;
	
	
	protected String strConfigId = "";

	
	
	public XMLNode()
	{
		strId = "";
		this.parentNode = null;
	}
	
	public XMLNode(XMLNode parentNode)
	{
		strId = "";
		this.parentNode = parentNode;
	}

	/**
	 * 获取父节点
	 * 
	 * @return
	 */
	public XMLNode getParentNode()
	{
		return this.parentNode;
	}

	/**
	 * 设置父节点
	 * @param parentNode
	 */
	public void setParentNode(XMLNode parentNode)
	{
		this.parentNode = parentNode;
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see SA.SRFramework.Base.XMLConfig#OnLoadNode(java.lang.String,
	 *      org.w3c.dom.Node)
	 */
	@Override
	public void OnLoadNode(String strName, Node xmlNode)
	{
		if (childNodes == null)
		{
			childNodes = new ArrayList<XMLNode>();
		}
		XMLNode node = new XMLNode(this);
		if (node.LoadConfig(xmlNode))
		{
			node.setParentNode(this);
			childNodes.add(node);
		}

	}

	public void AddNode(XMLNode node)
	{
		if (childNodes == null)
		{
			childNodes = new ArrayList<XMLNode>();
		}
		node.setParentNode(this);
		childNodes.add(node);
	}
	
	public void RemoveAllNodes(){
		this.childNodes = null;
	}
	
	public void RemoveNode(XMLNode node)
	{
		if (childNodes == null)
		{
			return;
		}
		
		childNodes.remove(node);
	}
	
	
	/**
	 * 按照指定位置增加节点
	 * @param nPos
	 * @param node
	 */
	public void AddNode(int nPos,XMLNode node)
	{
		if (childNodes == null)
		{
			childNodes = new ArrayList<XMLNode>();
		}
		node.setParentNode(this);
		childNodes.add(nPos,node);
	}
	

	public String getXMLNodeId()
	{
		return this.strXMLNodeId;
	}
	
	public void getXMLNodeId(String strXMLNodeId)
	{
		this.strXMLNodeId = strXMLNodeId;
	}

	public String getPXMLNodeId()
	{
		return this.strPXMLNodeId;
	}
	
	public void setPXMLNodeId(String strPXMLNodeId)
	{
		this.strPXMLNodeId = strPXMLNodeId;
	}
	

	public String getConfigId()
	{
		return this.strConfigId;
	}
	
	public void setConfigId(String strConfigId)
	{
		this.strConfigId = strConfigId;
	}
	
	public ArrayList<XMLNode> getChildNodes()
	{
		return childNodes;
	}

	
	
	
	

	 /**
     * 保存节点的信息
     *
     * @param xmlWriter SimpleXMLWriter
     * @return boolean
     */
    public boolean SaveCurNode(SimpleXMLWriter xmlWriter,boolean bSaveChild)
    {
        if(StringHelper.Length(strNodeName)!=0)
        {
            xmlWriter.WriteStartElement(strNodeName);
            //保存当前属性
            if(!SavePropertys(xmlWriter))
                return false;

            //保存子节点信息
            if(bSaveChild)
            {
            	if(!SaveChildNodes(xmlWriter))
            		return false;
            }
            xmlWriter.WriteEndElement();
        }
        return true;
    }
    
	

	/* (non-Javadoc)
	 * @see SA.SRFramework.Base.XMLConfig#SaveChildNodes(SA.SRFramework.XML.SimpleXMLWriter)
	 */
	@Override
	protected boolean SaveChildNodes(SimpleXMLWriter xmlWriter)
	{
		if(childNodes == null)
			return true;
		
		int nCount = childNodes.size();
		for(int i = 0 ;i<nCount;i++)
		{
			XMLNode childNode = childNodes.get(i);
			childNode.Save(xmlWriter);			
		}

		return super.SaveChildNodes(xmlWriter);
	}
	
	
	/**
	 * 通过节点名称获取所有的节点（含当前节点）
	 * @param strNodeName
	 * @param list
	 */
	public void GetAllNodeByNodeName(String strNodeName,ArrayList<XMLNode> list)
	{
		if(StringHelper.Compare(this.getNodeName(), strNodeName, true) == 0)
			list.add(this);
		
		
		if(childNodes == null)
			return ;
		
		int nCount = childNodes.size();
		for(int i = 0 ;i<nCount;i++)
		{
			XMLNode childNode = childNodes.get(i);
			childNode.GetAllNodeByNodeName(strNodeName,list);			
		}
	}
	
	public XMLNode GetChildNodeByNodeName(String strNodeName)
	{
		if(childNodes == null)
			return null;
		
		int nCount = childNodes.size();
		for(int i = 0 ;i<nCount;i++)
		{
			XMLNode childNode = childNodes.get(i);
			if(StringHelper.Compare(childNode.getNodeName(),strNodeName,true) == 0)
				return childNode;
		}
		return null;
	}
	
	
	public void GetChildNodeByNodeName(String strNodeName,ArrayList<XMLNode> list)
	{
		if(childNodes == null)
			return ;
		
		int nCount = childNodes.size();
		for(int i = 0 ;i<nCount;i++)
		{
			XMLNode childNode = childNodes.get(i);
			if(StringHelper.Compare(childNode.getNodeName(),strNodeName,true) == 0)
				list.add(childNode);
		}
	}
	
	
	public void GetChildNodeByNodeNameAndId(String strNodeName,String strId,ArrayList<XMLNode> list)
	{
		if(childNodes == null)
			return ;
		
		int nCount = childNodes.size();
		for(int i = 0 ;i<nCount;i++)
		{
			XMLNode childNode = childNodes.get(i);
			if(StringHelper.Compare(childNode.getNodeName(),strNodeName,true) == 0)
			{
				if(StringHelper.Compare(childNode.getID(),strId,true) == 0)
					list.add(childNode);
			}
		}
	}
	
	public void DeleteChildNodeByNodeNameAndId(String strNodeName,String strId)
	{
		if(childNodes == null)
			return ;
		
		int nCount = childNodes.size();
		List<XMLNode> list = new ArrayList<XMLNode>();
		for(int i = 0 ;i<nCount;i++)
		{
			XMLNode childNode = childNodes.get(i);
			if(StringHelper.Compare(childNode.getNodeName(),strNodeName,true) == 0)
			{
				if(StringHelper.Compare(childNode.getID(),strId,true) == 0){
					list.add(childNode);
					
				}
			}
		}
		for (Iterator iterator = list.iterator(); iterator.hasNext();) {
			XMLNode node = (XMLNode) iterator.next();
			this.RemoveNode(node);
		}
	}
	
	public XMLNode GetChildNodeByNodeNameAndId(String strNodeName,String strId)
	{
		if(childNodes == null)
			return null;
		
		int nCount = childNodes.size();
		for(int i = 0 ;i<nCount;i++)
		{
			XMLNode childNode = childNodes.get(i);
			if(StringHelper.Compare(childNode.getNodeName(),strNodeName,true) == 0)
			{
				if(StringHelper.Compare(childNode.getID(),strId,true) == 0)
					return childNode;
			}
		}
		return null;
	}
	
	public static XMLNode Load(String strPath)
	{
		try
		{
			DOMParser parser = new DOMParser();
			parser.parse(strPath);
			Document doc = parser.getDocument();

			XMLNode xmlNode = new XMLNode(null);
			xmlNode.LoadConfig(doc.getDocumentElement());
			return xmlNode;

		}
		catch (Exception ex)
		{
			ex.printStackTrace(System.out);
			return null;
		}
	}
	
	
	public static XMLNode LoadFromXML(String strXML)
	{
		try
		{
			InputSource is = new InputSource(new java.io.StringReader(strXML));
			DOMParser parser = new DOMParser();
			parser.parse(is);
			Document doc = parser.getDocument();

			XMLNode xmlNode = new XMLNode(null);
			xmlNode.LoadConfig(doc.getDocumentElement());
			return xmlNode;

		}
		catch (Exception ex)
		{
			ex.printStackTrace(System.out);
			return null;
		}
	}
	
	/**
	 * 写入配置文件
	 * @param rootNode
	 * @param strConfigPath
	 * @return
	 */
	public static boolean WriteToFile(XMLNode rootNode, String strConfigPath)
	{
		try
		{
			StringBuilder sb = new StringBuilder();
			SimpleXMLWriter writer = new SimpleXMLWriter(sb);
			writer.WriteRaw("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n");
			rootNode.Save(writer);

			OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(strConfigPath), "UTF-8");
			out.write(sb.toString());
			out.flush();
			out.close();
		}
		catch (Exception ex)
		{
			return false;
		}
		return true;
	}

	
	/**
	 * 将XML节点导出为字符串
	 * @param rootNode
	 * @return
	 */
	public static String Export(XMLNode rootNode)
	{
		try
		{
			StringBuilder sb = new StringBuilder();
			SimpleXMLWriter writer = new SimpleXMLWriter(sb);
			writer.WriteRaw("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n");
			rootNode.Save(writer);
			
			return sb.toString();
		}
		catch (Exception ex)
		{
			return "";
		}
	}

	/* (non-Javadoc)
	 * @see SA.SRFramework.Base.XMLConfig#Reset()
	 */
	@Override
	public void Reset()
	{
		
		super.Reset();
		childNodes = null;
	}
	
	public void loadSelfData(BaseDataEntity data){
		if(data == null) return;
		Enumeration keys = data.getParamList().keys();
		while (keys.hasMoreElements()){
			String strKey = (String)keys.nextElement();
			Object value = data.gpov(strKey);
			if(value instanceof BaseDataEntity 
					|| value instanceof BaseDataEntities)
				continue;
			
			String strValue = StringHelper.getValue(value);
			OnSetProperty( strKey, strValue);
		}
	}
	
	public void loadData(BaseDataEntity data,boolean bRestChildNodes){
		if(data == null) return;
		Enumeration keys = data.getParamList().keys();
		if(bRestChildNodes){
			this.RemoveAllNodes();
		}
		while (keys.hasMoreElements()){
			String strKey = (String)keys.nextElement();
			Object obj = data.gpov(strKey);
			if(obj instanceof BaseDataEntity){
				onLoadNode(strKey, (BaseDataEntity)obj,bRestChildNodes);
			}else if(obj instanceof BaseDataEntities){
				BaseDataEntities rows = (BaseDataEntities)obj;
				for (int i = 0; i < rows.size(); i++) {
					onLoadNode(strKey,rows.get(i),bRestChildNodes);
				}
			}else{
				OnSetProperty( strKey, data.gpsv(strKey));
			}
		}
		
	}
	
	public void onLoadNode(String nodeName,BaseDataEntity data,boolean bRestChildNodes){
		XMLNode node = GetChildNodeByNodeNameAndId(nodeName, data.gpsv("id"));
		if(node == null){
			node = new XMLNode();
			node.setNodeName(nodeName);
			this.AddNode(node);
		}
		node.loadData(data,bRestChildNodes);
		
	}
	
	public BaseDataEntities getChildBaseDataEntities(){
		BaseDataEntities rows = new BaseDataEntities();
		if(this.getChildNodes() != null){
			for (int i = 0; i < this.getChildNodes().size(); i++) {
				XMLNode childNode = this.getChildNodes().get(i);
				BaseDataEntity row = new BaseDataEntity();
				childNode.FillBaseDataEntity(row, false, true);
				rows.add(row);
			}
		}
		return rows;
	}
	
	public BaseDataEntity getBaseDataEntity(boolean breset,boolean bSaveChildNodes){
		return this.FillBaseDataEntity(new BaseDataEntity(), breset, bSaveChildNodes);
	}
	
	public BaseDataEntity FillBaseDataEntity(BaseDataEntity data,boolean breset,boolean bSaveChildNodes){
		if(data == null) return data;
		if(breset)data.Reset();
		
		if (StringHelper.Length(strId) != 0)
		{
			data.spsv(TagHelper.ID, strId);
		}

		if (extAttrList != null)
		{
			Enumeration enumeration = extAttrList.keys();
			while (enumeration.hasMoreElements())
			{
				String strKey = (String) enumeration.nextElement();
//				String strValue = (String) extAttrList.get(strKey);
//				if (!StringHelper.IsNullOrEmpty(strValue))
//					data.spsv(strKey, strValue);
				if(extAttrList.get(strKey)!= null)
					data.spov(strKey, extAttrList.get(strKey));
			}
		}

		if (!StringHelper.IsNullOrEmpty(strNodeValue))
		{
			String strTemp = strNodeValue.replace("\r", "");
			strTemp = strTemp.replace("\n", "");
			strTemp = strTemp.replace("&#xD;", "");
			strTemp = strTemp.replace("&#xA;", "");
			strTemp = strTemp.replace("\t", "");
			strTemp = strTemp.replace(" ", "");
			if (!StringHelper.IsNullOrEmpty(strTemp))
				data.spsv("NodeValue", strNodeValue);
		}
		
		if(bSaveChildNodes){
			if(this.getChildNodes() != null && this.getChildNodes().size() > 0){
				BaseDataEntities rows = new BaseDataEntities();
				for (int i = 0; i < this.getChildNodes().size(); i++) {
					BaseDataEntity childData = new BaseDataEntity();
					rows.add(childData);
				}
				data.spov("ChildNodes", rows);
			}
		}
		
		return data;
	}
	
	public int getIndexInParentChildNodes(){
		if(this.getParentNode() == null || this.getParentNode().getChildNodes() == null)return -1;
		List<XMLNode>  list = this.getParentNode().getChildNodes();
		for (int i = 0; i < list.size(); i++) {
			if(this == list.get(i))
				return i;
		}
		return -1;
	}

}
